/**
 * author      : dormi330
 * date        : 2018/6/24
 * project     : mybatis
 * description : 领域行为: 创建订单
 */

package com.deep.trade.domain.order;

import com.deep.trade.adaptor.required.IdService;
import com.deep.trade.adaptor.required.MemberAddress;
import com.deep.trade.adaptor.required.member.Member;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.deep.trade.adaptor.required.logistical.LogisticalService;
import com.deep.trade.adaptor.required.sku.ItemSkuService;
import com.deep.trade.adaptor.required.sku.Sku;
import com.deep.trade.common.TradeException;
import com.deep.trade.order.InDtoCreateOrder;
import com.deep.trade.order.InDtoCreateOrder.InDtoOrderItem;

import java.math.BigDecimal;
import java.util.*;

@Service
public class CommandPlaceOrder {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private IdService idService;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ItemSkuService itemSkuService;

    @Autowired
    private LogisticalService logisticalService;

    /**
     * 新建订单
     *
     * @param tenantCode         租户code
     * @param member             会员
     * @param address            地址
     * @param inDtoOrderItemList
     * @throws Exception
     */
    @Transactional
    public void placeOrder(
            String tenantCode,
            Member member,
            MemberAddress address,
            String remark,
            List<InDtoOrderItem> inDtoOrderItemList) throws Exception {

        List<TradeOrderSku> tradeOrderSkuList = tradeOrderSkuSetup(tenantCode, inDtoOrderItemList, member, address);

        // 拆单得到多个 TradeOrder 和 OrderDelivery
        Map<String, TradeOrder> tradeOrderMap = new HashMap<>();
        Map<String, OrderDelivery> orderDeliveryMap = new HashMap<>();

        for (TradeOrderSku tradeOrderSku : tradeOrderSkuList) {
            // tradeOrder
            String shopId = tradeOrderSku.getShopId();
            TradeOrder tradeOrder = tradeOrderMap.get(shopId);
            if (tradeOrder == null) {
                tradeOrder = tradeOrderFromSku(tradeOrderSku, member, remark);
                tradeOrderMap.put(shopId, tradeOrder);
            }
            tradeOrder.addTradeOrderSku(tradeOrderSku);

            // 地址信息
            if (null == orderDeliveryMap.get(shopId)) {
                OrderDelivery orderDelivery = splitOrderOfOrderDelivery(tenantCode, member.getId(), tradeOrder.getId(), address);
                orderDeliveryMap.put(shopId, orderDelivery);
            }
        }

        for (TradeOrder tradeOrder : tradeOrderMap.values()) {
            tradeOrder.calculateMoney();
        }
        // 创建 一个 OrderSummary
        OrderSummary orderSummary = createOrderSummary(tenantCode, member);
        for (TradeOrder tradeOrder : tradeOrderMap.values()) {
            orderSummary.addTradeOrder(tradeOrder);
        }
        orderSummary.calculateMoney();

        // 进行存储
        peresistNewOrder(orderSummary, tradeOrderMap.values(), orderDeliveryMap.values(), tradeOrderSkuList);

        // TODO 订单创建之后, 如果有支付超时限制, 则启动
    }

    private TradeOrder tradeOrderFromSku(TradeOrderSku tradeOrderSku, Member member, String remark) {
        TradeOrder tradeOrder = new TradeOrder();
        tradeOrder.setId(idService.uuid());
        tradeOrder.setTenantCode(tradeOrderSku.getTenantCode());
        tradeOrder.setCreatedBy(member.getId());
        tradeOrder.setUpdatedBy(member.getId());

        // orderSummaryId
        // orderType        暂不需要
        // orderChannel     暂不需要
        // code             暂不需要
        tradeOrder.setSellerId(tradeOrderSku.getSellerId());
        tradeOrder.setSellerName(tradeOrderSku.getSellerName());
        tradeOrder.setShopId(tradeOrderSku.getShopId());
        tradeOrder.setMemberId(member.getId());
        tradeOrder.setMemberName(member.getName());
        tradeOrder.setRemark(remark);
        // sellerRemark     暂不需要
        tradeOrder.setStatus(TradeOrder.STATUS_TO_BE_AUDITED);
        tradeOrder.setDiscountMoney(BigDecimal.ZERO);

        return tradeOrder;
    }


    private void peresistNewOrder(
            OrderSummary orderSummary,
            Collection<TradeOrder> tradeOrderList,
            Collection<OrderDelivery> orderDeliveryList,
            Collection<TradeOrderSku> tradeOrderSkuList) throws Exception {

        orderRepository.addOrderSummary(orderSummary);

        for (TradeOrder tradeOrder : tradeOrderList) {
            orderRepository.addTradeOrder(tradeOrder);
        }

        for (OrderDelivery orderDelivery : orderDeliveryList) {
            orderRepository.addOrderDelivery(orderDelivery);
        }

        for (TradeOrderSku tradeOrderSku : tradeOrderSkuList) {
            orderRepository.addOrderSku(tradeOrderSku);
        }
    }

    private OrderSummary createOrderSummary(String tenantCode, Member member) {
        OrderSummary orderSummary = new OrderSummary();
        orderSummary.setId(idService.uuid());
        orderSummary.setTenantCode(tenantCode);
        orderSummary.setCreatedBy(member.getId());
        orderSummary.setUpdatedBy(member.getId());
        orderSummary.setMemberId(member.getId());
        orderSummary.setMemberName(member.getName());

        orderSummary.setPlatformDiscountMoney(platformDiscount());

        return orderSummary;
    }

    // 计算平台折扣, 这部分逻辑暂时没有
    private BigDecimal platformDiscount() {
        return BigDecimal.ZERO;
    }


    // 拆单之 创建OrderDelivery
    private OrderDelivery splitOrderOfOrderDelivery(
            String tenantCode,
            String memberId,
            String tradeOrderId,
            MemberAddress address) {
        OrderDelivery orderDelivery = new OrderDelivery();
        orderDelivery.setId(idService.uuid());
        orderDelivery.setTenantCode(tenantCode);
        orderDelivery.setCreatedBy(memberId);
        orderDelivery.setUpdatedBy(memberId);
        orderDelivery.setTradeOrderId(tradeOrderId);

        orderDelivery.setProvinceName(address.getProviceName());
        orderDelivery.setCityName(address.getCityName());
        orderDelivery.setDistrictName(address.getDistrictName());
        orderDelivery.setStreetName(address.getStreetName());
        orderDelivery.setPostcode(address.getPostCode());
        orderDelivery.setReceiverName(address.getReceiverName());
        orderDelivery.setRecieverPhone(address.getReceiverPhone());
        orderDelivery.setDetailAddr(address.getDetailAddress());
        orderDelivery.setStatus(OrderDelivery.STATUS_NOT_DELIVERY);
        return orderDelivery;
    }


    /**
     * 组装 商品详情 数据接口
     *
     * @param inDtoOrderItemList
     * @return
     * @throws Exception
     */
    private List<TradeOrderSku> tradeOrderSkuSetup(
            String tenantCode,
            List<InDtoCreateOrder.InDtoOrderItem> inDtoOrderItemList,
            Member member,
            MemberAddress address) throws Exception {
        if (null == inDtoOrderItemList || inDtoOrderItemList.size() == 0) throw new TradeException("no item");

        List<TradeOrderSku> orderSkuArrayList = new ArrayList<>(inDtoOrderItemList.size());
        for (InDtoCreateOrder.InDtoOrderItem inDtoOrderItem : inDtoOrderItemList) {
            Sku skuFromItem = itemSkuService.skuOfId(tenantCode, inDtoOrderItem.getSkuId());        // TODO 优化, 不要 一次查询多个
            if (skuFromItem == null) throw new TradeException("item not exist, skuId=" + inDtoOrderItem.getSkuId());

            int quantity = inDtoOrderItem.getQuantity();
            if (quantity <= 0) throw new TradeException("item quantity illegal, quantity=" + quantity);

            // 计算价格
            BigDecimal freight = freightOfEachSku(skuFromItem.getId(), quantity, address);

            TradeOrderSku tradeOrderSku = new TradeOrderSku();
            tradeOrderSku.setTenantCode(tenantCode);
            tradeOrderSku.setCreatedBy(member.getId());
            tradeOrderSku.setUpdatedBy(member.getId());
            tradeOrderSku.setId(idService.uuid());
            tradeOrderSku.setSellerId(skuFromItem.getSellerId());
            tradeOrderSku.setSellerName(skuFromItem.getSellerName());
            tradeOrderSku.setShopId(skuFromItem.getShopId());
            tradeOrderSku.setItemId(skuFromItem.getShopId());
            tradeOrderSku.setItemName(skuFromItem.getItemName());
            tradeOrderSku.setSkuId(skuFromItem.getId());
            tradeOrderSku.setSkuCode(skuFromItem.getSkuCode());
            tradeOrderSku.setBrandId(skuFromItem.getBrandId());
            tradeOrderSku.setQuantity(quantity);
            // money
            tradeOrderSku.setDiscountMoney(BigDecimal.ZERO);
            tradeOrderSku.setPriceMoney(skuFromItem.getPrice());
            tradeOrderSku.setFreightMoney(freight);
            //
            tradeOrderSku.calculateMoney();

            //
            orderSkuArrayList.add(tradeOrderSku);
        }
        return orderSkuArrayList;
    }

    /**
     * 计算运费
     */
    private BigDecimal freightOfEachSku(String skuId, int quanlity, MemberAddress address) throws Exception {
        return logisticalService.freightOfSku(skuId, quanlity, address);
    }
}
